﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using PmSoft.Core.Domain;
using PmSoft.Core.Domain.Auth;

namespace PmSoft.Core;

/// <summary>
/// 应用程序上下文，用于管理应用程序状态和服务访问
/// </summary>
public class ApplicationContext : IApplicationContext
{
	private readonly IHttpContextAccessor _httpContextAccessor;
	private readonly IServiceProvider _serviceProvider;

	/// <summary>
	/// 构造函数，初始化服务提供者和 HTTP 上下文访问器
	/// </summary>
	/// <param name="serviceProvider">依赖注入服务提供者</param>
	/// <param name="httpContextAccessor">HTTP 上下文访问器</param>
	public ApplicationContext(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor)
	{
		_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
		_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
	}

	/// <summary>
	/// 获取服务提供者实例
	/// </summary>
	public IServiceProvider ServiceProvider => _serviceProvider;

	/// <summary>
	/// 获取必需的服务实例
	/// </summary>
	/// <typeparam name="TService">服务类型</typeparam>
	/// <returns>服务实例</returns>
	/// <exception cref="InvalidOperationException">当请求的服务不存在时抛出异常</exception>
	public TService GetRequiredService<TService>() where TService : notnull
	{
		try
		{
			return _serviceProvider.GetRequiredService<TService>();
		}
		catch (Exception ex)
		{
			throw new InvalidOperationException($"无法获取服务类型 {typeof(TService).FullName} 的实例.", ex);
		}
	}

	/// <summary>
	/// HTTP上下文信息
	/// </summary>
	public HttpContext HttpContext => _httpContextAccessor.HttpContext;

	/// <summary>
	/// 当前认证用户信息
	/// </summary>
	public IAuthedUser? CurrentUser
	{
		get
		{
			var context = _httpContextAccessor.HttpContext;
			if (context == null)
				throw new InvalidOperationException("当前请求的 HTTP 上下文为 null，无法获取认证用户信息.");

			if (context.Items.TryGetValue("CurrentUser", out var user) && user is IAuthedUser authedUser)
			{
				return authedUser;
			}
			return default;
			//throw new InvalidOperationException("当前 HTTP 上下文中未找到认证用户信息.");
		}
	}

	/// <summary>
	/// 获取当前已认证的用户信息，保证非空。
	/// 如果当前用户未认证，将抛出异常。
	/// </summary>
	/// <exception cref="InvalidOperationException">当当前用户未认证时抛出。</exception>
	public IAuthedUser RequiredCurrentUser
	{
		get
		{
			if (CurrentUser == null)
				throw new InvalidOperationException("当前用户未认证。");
			return CurrentUser;
		}
	}

	/// <summary>
	/// 当前客户端信息
	/// </summary>
	public IClientInfoProvider ClientInfo => GetRequiredService<IClientInfoProvider>();
}
